home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / awt / FlowLayout.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  14.6 KB  |  496 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)FlowLayout.java    1.31 98/08/17
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.io.ObjectInputStream;
  17. import java.io.IOException;
  18.  
  19. /**
  20.  * A flow layout arranges components in a left-to-right flow, much
  21.  * like lines of text in a paragraph. Flow layouts are typically used
  22.  * to arrange buttons in a panel. It will arrange
  23.  * buttons left to right until no more buttons fit on the same line.
  24.  * Each line is centered.
  25.  * <p>
  26.  * For example, the following picture shows an applet using the flow
  27.  * layout manager (its default layout manager) to position three buttons:
  28.  * <p>
  29.  * <img src="doc-files/FlowLayout-1.gif"
  30.  * ALT="Graphic of Layout for Three Buttons"
  31.  * ALIGN=center HSPACE=10 VSPACE=7>
  32.  * <p>
  33.  * Here is the code for this applet:
  34.  * <p>
  35.  * <hr><blockquote><pre>
  36.  * import java.awt.*;
  37.  * import java.applet.Applet;
  38.  *
  39.  * public class myButtons extends Applet {
  40.  *     Button button1, button2, button3;
  41.  *     public void init() {
  42.  *         button1 = new Button("Ok");
  43.  *         button2 = new Button("Open");
  44.  *         button3 = new Button("Close");
  45.  *         add(button1);
  46.  *         add(button2);
  47.  *         add(button3);
  48.  *     }
  49.  * }
  50.  * </pre></blockquote><hr>
  51.  * <p>
  52.  * A flow layout lets each component assume its natural (preferred) size.
  53.  *
  54.  * @version     1.31, 08/17/98
  55.  * @author     Arthur van Hoff
  56.  * @author     Sami Shaio
  57.  * @since       JDK1.0
  58.  */
  59. public class FlowLayout implements LayoutManager, java.io.Serializable {
  60.  
  61.     /**
  62.      * This value indicates that each row of components
  63.      * should be left-justified.
  64.      */
  65.     public static final int LEFT     = 0;
  66.  
  67.     /**
  68.      * This value indicates that each row of components
  69.      * should be centered.
  70.      */
  71.     public static final int CENTER     = 1;
  72.  
  73.     /**
  74.      * This value indicates that each row of components
  75.      * should be right-justified.
  76.      */
  77.     public static final int RIGHT     = 2;
  78.  
  79.     /**
  80.      * This value indicates that each row of components
  81.      * should be justified to the leading edge of the container's
  82.      * orientation, e.g. to the left in left-to-right orientations.
  83.      *
  84.      * @see     java.awt.Component#getComponentOrientation
  85.      * @see     java.awt.ComponentOrientation
  86.      * @since   JDK1.2
  87.      * Package-private pending API change approval
  88.      */
  89.     public static final int LEADING    = 3;
  90.  
  91.     /**
  92.      * This value indicates that each row of components
  93.      * should be justified to the leading edge of the container's
  94.      * orientation, e.g. to the right in left-to-right orientations.
  95.      *
  96.      * @see     java.awt.Component#getComponentOrientation
  97.      * @see     java.awt.ComponentOrientation
  98.      * @since   JDK1.2
  99.      * Package-private pending API change approval
  100.      */
  101.     public static final int TRAILING = 4;
  102.  
  103.     /**
  104.      * <code>align</code> is the proprty that determines
  105.      * how each row distributes empty space.
  106.      * It can be one of the following three values :
  107.      * <code>LEFT</code>
  108.      * <code>RIGHT</code>
  109.      * <code>CENTER</code>
  110.      *
  111.      * @serial
  112.      * @see getAlignment()
  113.      * @see setAlignment()
  114.      */
  115.     int align;          // This is for 1.1 serialization compatibilitys
  116.     /**
  117.      * <code>newAlign</code> is the property that determines
  118.      * how each row distributes empty space for JDK's >= JDK1.2.
  119.      * It can be one of the following three values :
  120.      * <code>LEFT</code>
  121.      * <code>RIGHT</code>
  122.      * <code>CENTER</code>
  123.      *
  124.      * @serial
  125.      * @since JDK 1.2
  126.      * @see getAlignment()
  127.      * @see setAlignment()
  128.      */
  129.     int newAlign;       // This is the one we actually use
  130.     /**
  131.      * The flow layout manager allows a seperation of
  132.      * components with gaps.  The horizontal gap will
  133.      * specify the space between components.
  134.      *
  135.      * @serial
  136.      * @see getHgap()
  137.      * @see setHgap()
  138.      */
  139.     int hgap;
  140.     /**
  141.      * The flow layout manager allows a seperation of
  142.      * components with gaps.  The vertical gap will
  143.      * specify the space between rows.
  144.      *
  145.      * @serial
  146.      * @see getVgap()
  147.      * @see setVgap()
  148.      */
  149.     int vgap;
  150.  
  151.     /*
  152.      * JDK 1.1 serialVersionUID
  153.      */
  154.      private static final long serialVersionUID = -7262534875583282631L;
  155.  
  156.     /**
  157.      * Constructs a new Flow Layout with a centered alignment and a
  158.      * default 5-unit horizontal and vertical gap.
  159.      */
  160.     public FlowLayout() {
  161.     this(CENTER, 5, 5);
  162.     }
  163.  
  164.     /**
  165.      * Constructs a new Flow Layout with the specified alignment and a
  166.      * default 5-unit horizontal and vertical gap.
  167.      * The value of the alignment argument must be one of
  168.      * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
  169.      * or <code>FlowLayout.CENTER</code>.
  170.      * @param align the alignment value
  171.      */
  172.     public FlowLayout(int align) {
  173.     this(align, 5, 5);
  174.     }
  175.  
  176.     /**
  177.      * Creates a new flow layout manager with the indicated alignment
  178.      * and the indicated horizontal and vertical gaps.
  179.      * <p>
  180.      * The value of the alignment argument must be one of
  181.      * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
  182.      * or <code>FlowLayout.CENTER</code>.
  183.      * @param      align   the alignment value.
  184.      * @param      hgap    the horizontal gap between components.
  185.      * @param      vgap    the vertical gap between components.
  186.      */
  187.     public FlowLayout(int align, int hgap, int vgap) {
  188.     this.hgap = hgap;
  189.     this.vgap = vgap;
  190.         setAlignment(align);
  191.     }
  192.  
  193.     /**
  194.      * Gets the alignment for this layout.
  195.      * Possible values are <code>FlowLayout.LEFT</code>,
  196.      * <code>FlowLayout.RIGHT</code>, or <code>FlowLayout.CENTER</code>.
  197.      * @return     the alignment value for this layout.
  198.      * @see    * @see        java.awt.FlowLayout#setAlignment
  199.      * @since      JDK1.1
  200.      */
  201.     public int getAlignment() {
  202.     return newAlign;
  203.     }
  204.  
  205.     /**
  206.      * Sets the alignment for this layout.
  207.      * Possible values are <code>FlowLayout.LEFT</code>,
  208.      * <code>FlowLayout.RIGHT</code>, and <code>FlowLayout.CENTER</code>.
  209.      * @param      align the alignment value.
  210.      * @see        java.awt.FlowLayout#getAlignment
  211.      * @since      JDK1.1
  212.      */
  213.     public void setAlignment(int align) {
  214.     this.newAlign = align;
  215.  
  216.         // this.align is used only for serialization compatibility,
  217.         // so set it to a value compatible with the 1.1 version
  218.         // of the class
  219.  
  220.         switch (align) {
  221.     case LEADING:
  222.             this.align = LEFT;
  223.         break;
  224.     case TRAILING:
  225.             this.align = RIGHT;
  226.         break;
  227.         default:
  228.             this.align = align;
  229.         break;
  230.         }
  231.     }
  232.  
  233.     /**
  234.      * Gets the horizontal gap between components.
  235.      * @return     the horizontal gap between components.
  236.      * @see        java.awt.FlowLayout#setHgap
  237.      * @since      JDK1.1
  238.      */
  239.     public int getHgap() {
  240.     return hgap;
  241.     }
  242.  
  243.     /**
  244.      * Sets the horizontal gap between components.
  245.      * @param hgap the horizontal gap between components
  246.      * @see        java.awt.FlowLayout#getHgap
  247.      * @since      JDK1.1
  248.      */
  249.     public void setHgap(int hgap) {
  250.     this.hgap = hgap;
  251.     }
  252.  
  253.     /**
  254.      * Gets the vertical gap between components.
  255.      * @return     the vertical gap between components.
  256.      * @see        java.awt.FlowLayout#setVgap
  257.      * @since      JDK1.1
  258.      */
  259.     public int getVgap() {
  260.     return vgap;
  261.     }
  262.  
  263.     /**
  264.      * Sets the vertical gap between components.
  265.      * @param vgap the vertical gap between components
  266.      * @see        java.awt.FlowLayout#getVgap
  267.      * @since      JDK1.1
  268.      */
  269.     public void setVgap(int vgap) {
  270.     this.vgap = vgap;
  271.     }
  272.  
  273.     /**
  274.      * Adds the specified component to the layout. Not used by this class.
  275.      * @param name the name of the component
  276.      * @param comp the component to be added
  277.      */
  278.     public void addLayoutComponent(String name, Component comp) {
  279.     }
  280.  
  281.     /**
  282.      * Removes the specified component from the layout. Not used by
  283.      * this class.
  284.      * @param comp the component to remove
  285.      * @see       java.awt.Container#removeAll
  286.      */
  287.     public void removeLayoutComponent(Component comp) {
  288.     }
  289.  
  290.     /**
  291.      * Returns the preferred dimensions for this layout given the components
  292.      * in the specified target container.
  293.      * @param target the component which needs to be laid out
  294.      * @return    the preferred dimensions to lay out the
  295.      *                    subcomponents of the specified container.
  296.      * @see Container
  297.      * @see #minimumLayoutSize
  298.      * @see       java.awt.Container#getPreferredSize
  299.      */
  300.     public Dimension preferredLayoutSize(Container target) {
  301.       synchronized (target.getTreeLock()) {
  302.     Dimension dim = new Dimension(0, 0);
  303.     int nmembers = target.getComponentCount();
  304.  
  305.     for (int i = 0 ; i < nmembers ; i++) {
  306.         Component m = target.getComponent(i);
  307.         if (m.visible) {
  308.         Dimension d = m.getPreferredSize();
  309.         dim.height = Math.max(dim.height, d.height);
  310.         if (i > 0) {
  311.             dim.width += hgap;
  312.         }
  313.         dim.width += d.width;
  314.         }
  315.     }
  316.     Insets insets = target.getInsets();
  317.     dim.width += insets.left + insets.right + hgap*2;
  318.     dim.height += insets.top + insets.bottom + vgap*2;
  319.     return dim;
  320.       }
  321.     }
  322.  
  323.     /**
  324.      * Returns the minimum dimensions needed to layout the components
  325.      * contained in the specified target container.
  326.      * @param target the component which needs to be laid out
  327.      * @return    the minimum dimensions to lay out the
  328.      *                    subcomponents of the specified container.
  329.      * @see #preferredLayoutSize
  330.      * @see       java.awt.Container
  331.      * @see       java.awt.Container#doLayout
  332.      */
  333.     public Dimension minimumLayoutSize(Container target) {
  334.       synchronized (target.getTreeLock()) {
  335.     Dimension dim = new Dimension(0, 0);
  336.     int nmembers = target.getComponentCount();
  337.  
  338.     for (int i = 0 ; i < nmembers ; i++) {
  339.         Component m = target.getComponent(i);
  340.         if (m.visible) {
  341.         Dimension d = m.getMinimumSize();
  342.         dim.height = Math.max(dim.height, d.height);
  343.         if (i > 0) {
  344.             dim.width += hgap;
  345.         }
  346.         dim.width += d.width;
  347.         }
  348.     }
  349.     Insets insets = target.getInsets();
  350.     dim.width += insets.left + insets.right + hgap*2;
  351.     dim.height += insets.top + insets.bottom + vgap*2;
  352.     return dim;
  353.       }
  354.     }
  355.  
  356.     /**
  357.      * Centers the elements in the specified row, if there is any slack.
  358.      * @param target the component which needs to be moved
  359.      * @param x the x coordinate
  360.      * @param y the y coordinate
  361.      * @param width the width dimensions
  362.      * @param height the height dimensions
  363.      * @param rowStart the beginning of the row
  364.      * @param rowEnd the the ending of the row
  365.      */
  366.     private void moveComponents(Container target, int x, int y, int width, int height,
  367.                                 int rowStart, int rowEnd, boolean ltr) {
  368.       synchronized (target.getTreeLock()) {
  369.     switch (newAlign) {
  370.     case LEFT:
  371.         x += ltr ? 0 : width;
  372.         break;
  373.     case CENTER:
  374.         x += width / 2;
  375.         break;
  376.     case RIGHT:
  377.         x += ltr ? width : 0;
  378.         break;
  379.     case LEADING:
  380.         break;
  381.     case TRAILING:
  382.         x += width;
  383.         break;
  384.     }
  385.     for (int i = rowStart ; i < rowEnd ; i++) {
  386.         Component m = target.getComponent(i);
  387.         if (m.visible) {
  388.             if (ltr) {
  389.                 m.setLocation(x, y + (height - m.height) / 2);
  390.             } else {
  391.                 m.setLocation(target.width - x - m.width, y + (height - m.height) / 2);
  392.                 }
  393.                 x += m.width + hgap;
  394.         }
  395.     }
  396.       }
  397.     }
  398.  
  399.     /**
  400.      * Lays out the container. This method lets each component take
  401.      * its preferred size by reshaping the components in the
  402.      * target container in order to satisfy the constraints of
  403.      * this <code>FlowLayout</code> object.
  404.      * @param target the specified component being laid out.
  405.      * @see Container
  406.      * @see       java.awt.Container#doLayout
  407.      */
  408.     public void layoutContainer(Container target) {
  409.       synchronized (target.getTreeLock()) {
  410.     Insets insets = target.getInsets();
  411.     int maxwidth = target.width - (insets.left + insets.right + hgap*2);
  412.     int nmembers = target.getComponentCount();
  413.     int x = 0, y = insets.top + vgap;
  414.     int rowh = 0, start = 0;
  415.  
  416.         boolean ltr = target.getComponentOrientation().isLeftToRight();
  417.  
  418.     for (int i = 0 ; i < nmembers ; i++) {
  419.         Component m = target.getComponent(i);
  420.         if (m.visible) {
  421.         Dimension d = m.getPreferredSize();
  422.         m.setSize(d.width, d.height);
  423.  
  424.         if ((x == 0) || ((x + d.width) <= maxwidth)) {
  425.             if (x > 0) {
  426.             x += hgap;
  427.             }
  428.             x += d.width;
  429.             rowh = Math.max(rowh, d.height);
  430.         } else {
  431.             moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, i, ltr);
  432.             x = d.width;
  433.             y += vgap + rowh;
  434.             rowh = d.height;
  435.             start = i;
  436.         }
  437.         }
  438.     }
  439.     moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, nmembers, ltr);
  440.       }
  441.     }
  442.  
  443.     //
  444.     // the internal serial version which says which version was written
  445.     // - 0 (default) for versions before JDK 1.2
  446.     // - 1 for version >= JDK 1.2, which includes "newAlign" field
  447.     //
  448.     private static final int currentSerialVersion = 1;
  449.     /**
  450.      * This represent the <code>currentSerialVersion</code>
  451.      * which is bein used.  It will be one of two values :
  452.      * <code>0</code> versions before JDK 1.2.
  453.      * <code>1</code> versions after  JDK 1.2.
  454.      *
  455.      * @serial
  456.      * @since JDK 1.2
  457.      */
  458.     private int serialVersionOnStream = currentSerialVersion;
  459.  
  460.     /**
  461.      * Read this object out of a serialization stream, handling
  462.      * objects written by older versions of the class that didn't contain all
  463.      * of the fields we use now..
  464.      */
  465.     private void readObject(ObjectInputStream stream)
  466.          throws IOException, ClassNotFoundException
  467.     {
  468.         stream.defaultReadObject();
  469.  
  470.         if (serialVersionOnStream < 1) {
  471.             // "newAlign" field wasn't present, so use the old "align" field.
  472.             setAlignment(this.align);
  473.         }
  474.         serialVersionOnStream = currentSerialVersion;
  475.     }
  476.  
  477.     /**
  478.      * Returns a string representation of this <code>FlowLayout</code>
  479.      * object and its values.
  480.      * @return     a string representation of this layout.
  481.      */
  482.     public String toString() {
  483.     String str = "";
  484.     switch (align) {
  485.       case LEFT:        str = ",align=left"; break;
  486.       case CENTER:      str = ",align=center"; break;
  487.       case RIGHT:       str = ",align=right"; break;
  488.       case LEADING:     str = ",align=leading"; break;
  489.       case TRAILING:    str = ",align=trailing"; break;
  490.     }
  491.     return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
  492.     }
  493.  
  494.  
  495. }
  496.